package com.fanshuai.soring.boot.webflux.metrics;

import io.prometheus.client.Counter;
import io.prometheus.client.Summary;
import org.springframework.boot.web.reactive.filter.OrderedWebFilter;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;

public class ReactiveMetricsFilter implements OrderedWebFilter {
    Summary httpLatency = Summary.build()
            .name("http_latency")
            .help("http_latency")
            .quantile(0.5d, 0.1)
            .quantile(0.75d, 0.05)
            .quantile(0.95d, 0.03)
            .quantile(0.98d, 0.01)
            .labelNames("uri")
            .register();

    Counter successCount = Counter.build()
            .name("success_count")
            .help("success_count")
            .labelNames("uri")
            .register();

    Counter errCount = Counter.build()
            .name("error_count")
            .help("error_count")
            .labelNames("uri")
            .register();

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 1;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        long start = System.currentTimeMillis();
        String uri = exchange.getRequest().getURI().getPath();

        Mono<Void> result = Mono.<Void>empty();
        try {
            result = chain.filter(exchange);
            successCount.labels(uri).inc();
            successCount.labels("all").inc();
        } catch (Exception e) {
            errCount.labels(uri).inc();
            errCount.labels("all").inc();
            throw e;
        } finally {
            long time = System.currentTimeMillis() - start;
            httpLatency.labels(uri).observe(time);
            httpLatency.labels("all").observe(time);
        }
        return result;
    }
}
